package com.lutzyt.delivery.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lutzyt.delivery.bean.*;
import com.lutzyt.delivery.mapper.OrderDAO;
import com.lutzyt.delivery.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author zyt
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class OrderServiceImpl extends ServiceImpl<OrderDAO, Order> implements OrderService {

  private OrderDAO orderDAO;
  private CustomerService customerService;
  private OrderItemService orderItemService;
  private DiscountCouponItemService discountCouponItemService;
  private OrderCommentService orderCommentService;
  private HorsemanService horsemanService;
  private HorsemanAccountFlowService accountFlowService;
  private OrderStateFlowService orderStateFlowService;

  @Transactional(readOnly = true)
  @Override
  public Order findById(Integer id) {
    final Order order = orderDAO.selectById(id);
    this.setComment(order);
    return order;
  }

  private void setComment(Order order){
    OrderComment comment = orderCommentService.findByOrderId(order.getId());
    if (comment != null){
      order.setComment(comment.getContext());
    }
  }

  @Transactional(readOnly = true)
  @Override
  public IPage<Order> findByPage(int pageNum, int pageSize) {
    return orderDAO.selectPage(new Page<>(pageNum, pageSize), null);
  }

  @Override
  public void insert(Order order) {
    order.setState("INIT");
    Integer customerId = order.getCustomerId();
    final String username = customerService.findById(customerId).getUsername();
    order.setCustomerName(username);
    order.setAmount(order.getAmount().divide(BigDecimal.valueOf(100)));
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    Order todayLastOrder = this.lambdaQuery().eq(Order::getCreateDate, sdf.format(new Date())).orderByDesc(Order::getId).last("limit 1").one();
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
    String orderNumber = todayLastOrder == null? simpleDateFormat.format(new Date())+"0000001" : String.valueOf((Long.parseLong(todayLastOrder.getNumber())+1));
    order.setNumber(orderNumber);
    order.setCreateTime(new Date());
    order.setCreateDate(new Date());
    orderDAO.insert(order);
    // 插入订单行
    List<OrderItem> items = order.getList();
    items.forEach(orderItem -> {
      orderItem.setOrderId(order.getId());
      orderItemService.insert(orderItem);
    });
    // 修改优惠券的使用状态
    Integer discountId = order.getDiscountCouponId();
    if (discountId!=null){
      //
      final DiscountCouponItem item = discountCouponItemService.lambdaQuery()
          .eq(DiscountCouponItem::getDiscountCouponId, discountId)
          .eq(DiscountCouponItem::getCustomerId, customerId)
          .one();
      if (item == null ){
        throw new RuntimeException("该优惠券不存在，请刷新界面后重新选择");
      }
      if ("USED".equals(item.getState())) {
        throw new RuntimeException("该优惠券以使用，请刷新界面后重新选择");
      }
      item.setOrderId(order.getId());
      item.setState("USED");
      discountCouponItemService.updateById(item);
    }
    OrderStateFlow orderStateFlow = new OrderStateFlow();
    orderStateFlow.setOrderId(order.getId());
    orderStateFlow.setAction("INIT");
    orderStateFlow.setNewState("INIT");
    orderStateFlowService.insert(orderStateFlow);
  }

  @Override
  public void replay(Integer id) {
    final Order order = this.getById(id);
    if (!"INIT".equals(order.getState())){
      throw new RuntimeException("订单状态以更改，请稍后尝试");
    }
    order.setState("INIT2");
    this.updateById(order);
    OrderStateFlow orderStateFlow = new OrderStateFlow();
    orderStateFlow.setOrderId(order.getId());
    orderStateFlow.setAction("INIT2");
    orderStateFlow.setNewState("INIT2");
    orderStateFlowService.insert(orderStateFlow);
  }

  @Override
  public void delivery(Integer id) {
    final Order order = this.getById(id);
    if (!"DELIVERY".equals(order.getState())){
      throw new RuntimeException("订单状态以更改，请稍后尝试");
    }
    order.setState("COMMENT");
    final Horseman horseman = horsemanService.findById(order.getHorsemanId());
    int bal = order.getAmount().intValue()/50+3;
    log.info("订单佣金:{}", bal);
    horseman.setBalance(horseman.getBalance().add(BigDecimal.valueOf(bal)));
    this.updateById(order);
    horsemanService.update(horseman);
    HorsemanAccountFlow flow = new HorsemanAccountFlow();
    flow.setAmount(BigDecimal.valueOf(bal));
    flow.setHorsemanId(horseman.getId());
    flow.setAction("ADD");
    accountFlowService.save(flow);
    OrderStateFlow orderStateFlow = new OrderStateFlow();
    orderStateFlow.setOrderId(order.getId());
    orderStateFlow.setAction("DELIVERY");
    orderStateFlow.setNewState("COMMENT");
    orderStateFlowService.insert(orderStateFlow);
  }

  @Override
  public void update(Order order) {
    orderDAO.updateById(order);
  }

  @Override
  public void deleteById(Integer id) {
    orderDAO.deleteById(id);
  }

  @Override
  public List<Order> findByCustomerId(Integer id) {
    final List<Order> list = this.lambdaQuery().eq(Order::getCustomerId, id).list();

    return list;
  }

  @Override
  public List<Order> findByHorsemanId(Integer id) {
    final List<Order> list = this.lambdaQuery().eq(Order::getHorsemanId, id).list();

    return list;
  }

  @Override
  public List<Order> initList() {
    final List<Order> list = this.lambdaQuery().eq(Order::getState, "INIT2").list();
    return list;
  }

  @Override
  public void takeIn(String id, String orderId) {
    final Horseman horseman = horsemanService.getById(id);
    final Order order = this.getById(orderId);
    if (!order.getState().equals("INIT2")){
      throw new RuntimeException("订单状态已经被更改，请刷新再试");
    }
    order.setHorsemanId(horseman.getId());
    order.setHorsemanName(horseman.getUsername());
    order.setState("DELIVERY");
    this.updateById(order);
    OrderStateFlow orderStateFlow = new OrderStateFlow();
    orderStateFlow.setOrderId(order.getId());
    orderStateFlow.setAction("INIT2");
    orderStateFlow.setNewState("DELIVERY");
    orderStateFlowService.insert(orderStateFlow);
  }

  @Autowired
  public void setOrderStateFlowService(OrderStateFlowService orderStateFlowService) {
    this.orderStateFlowService = orderStateFlowService;
  }

  @Autowired
  public void setAccountFlowService(HorsemanAccountFlowService accountFlowService) {
    this.accountFlowService = accountFlowService;
  }

  @Autowired
  public void setHorsemanService(HorsemanService horsemanService) {
    this.horsemanService = horsemanService;
  }

  @Autowired
  public void setOrderCommentService(OrderCommentService orderCommentService) {
    this.orderCommentService = orderCommentService;
  }

  @Autowired
  public void setDiscountCouponItemService(DiscountCouponItemService discountCouponItemService) {
    this.discountCouponItemService = discountCouponItemService;
  }

  @Autowired
  public void setOrderItemService(OrderItemService orderItemService) {
    this.orderItemService = orderItemService;
  }

  @Autowired
  public void setCustomerService(CustomerService customerService) {
    this.customerService = customerService;
  }

  @Autowired
  public void setOrderDAO(OrderDAO orderDAO) {
    this.orderDAO = orderDAO;
  }
}